<?php

namespace Framework\Foundation\Entity;

use App\Exceptions\BusinessException;

/**
 * Class RestEntity
 * @package Framework\Foundation\Entity
 * @see framework/Foundation/Rest/ResourceConverter.php 有方法可以共用
 */
class BaseEntity implements \arrayaccess
{
    use EntityExpand;

    protected static $connection = 'default';
    protected $info = [];

    public function __construct(array $info)
    {
        $this->info = $info;
    }

    public function __call($name, $arguments)
    {
        $field = $this->unCamelStyle($name);
        if (isset($this->info[$field])) {
            return $this->info[$field];
        }

        throw new BusinessException("实体类不包含元素：" . $field);
    }

    /**
     * 重置某个key的值
     * @param $key
     * @param $value
     * @return bool
     */
    public function set($key, $value)
    {
        $this->info[$key] = $value;
        return true;
    }

    /**
     * 重置实体包含的数据， 尽量少用
     * @param $info
     * @return $this
     */
    public function reFullWith($info)
    {
        $this->info = $info;
        return $this;
    }

    /**
     * 获取实体的数据
     * @return array
     */
    public function getInfo()
    {
        return $this->info;
    }

    /**
     * camelize
     * 下划线转驼峰
     * 思路:
     * step1.原字符串转小写,原字符串中的分隔符用空格替换,在字符串开头加上分隔符
     * step2.将字符串中每个单词的首字母转换为大写,再去空格,去字符串首部附加的分隔符.
     */
    public function camelStyle($uncamelized_words, $separator = '_')
    {
        $uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words));
        return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator);
    }

    /**
     * uncamelize
     * 驼峰命名转下划线命名
     * 思路:
     * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
     * @param $camelCaps
     * @param string $separator
     * @return string
     */
    public function unCamelStyle($camelCaps, $separator = '_')
    {
        return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
    }

    /**
     * 检查键是否存在
     * @param string $key
     * @return bool
     */
    public function has(string $key)
    {
        if (isset($this->info[$key])) {
            return true;
        }

        return false;
    }

    /**
     * 键存在则返回值，键不存在则抛出异常
     * @param string $key
     * @return mixed
     * @throws BusinessException
     */
    public function getOrException(string $key)
    {
        if (isset($this->info[$key])) {
            return $this->info[$key];
        }

        throw new BusinessException("实体类不包含元素：" . $key);
    }

    public function getOrDefault(string $key, $default = null)
    {
        if (isset($this->info[$key])) {
            return $this->info[$key];
        }

        return $default;
    }

    public function offsetExists($offset)
    {
        return isset($this->info[$offset]);
    }

    public function offsetGet($offset)
    {
        return $this->info[$offset] ?? null;
    }

    public function offsetSet($offset, $value)
    {
        if (is_null($offset)) {
            $this->info = $value;
        } else {
            $this->info[$offset] = $value;
        }
    }

    public function offsetUnset($offset)
    {
        unset($this->info[$offset]);
    }
}
